package com.zk.yygh.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.wxpay.sdk.WXPayUtil;
import com.zk.yygh.enums.OrderStatusEnum;
import com.zk.yygh.enums.PaymentStatusEnum;
import com.zk.yygh.helper.HttpRequestHelper;
import com.zk.yygh.hosp.exception.HospitalException;
import com.zk.yygh.hosp.result.ResultCodeEnum;
import com.zk.yygh.hosp_client.service.HospFeignClient;
import com.zk.yygh.model.order.OrderInfo;
import com.zk.yygh.model.order.PaymentInfo;
import com.zk.yygh.order.mapper.PaymentMapper;
import com.zk.yygh.order.service.OrderService;
import com.zk.yygh.order.service.PaymentService;
import com.zk.yygh.order.utils.ConstantPropertiesUtils;
import com.zk.yygh.order.utils.HttpClient;
import com.zk.yygh.vo.order.SignInfoVo;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author: 张凯
 * @date: 2022/6/22 - 17:22
 */
@Service
public class PaymentServiceImpl extends ServiceImpl<PaymentMapper, PaymentInfo> implements PaymentService {

    @Autowired
    private OrderService orderService;

    @Autowired
    private HospFeignClient hospFeignClient;

    //添加支付信息
    @Override
    public void savePaymentInfo(OrderInfo order, Integer paymentType) {
        //1.向数据库中查询是否存在该订单
        QueryWrapper<PaymentInfo> wrapper=new QueryWrapper<>();
        wrapper.eq("order_id",order.getId());
        wrapper.eq("payment_type",paymentType);
        Integer count = baseMapper.selectCount(wrapper);
        if (count>0){
            //存在就直接返回
            return;
        }
        //2.不存在就创建订单
        PaymentInfo paymentInfo=new PaymentInfo();
        paymentInfo.setCreateTime(new Date());
        paymentInfo.setOrderId(order.getId());
        paymentInfo.setPaymentType(paymentType);
        paymentInfo.setOutTradeNo(order.getOutTradeNo());
        paymentInfo.setPaymentStatus(PaymentStatusEnum.UNPAID.getStatus());
        String subject = new DateTime(order.getReserveDate()).toString("yyyy-MM-dd")+"|"+order.getHosname()+"|"+order.getDepname()+"|"+order.getTitle();
        paymentInfo.setSubject(subject);
        paymentInfo.setTotalAmount(order.getAmount());
        //3.执行添加订单操作
        baseMapper.insert(paymentInfo);
    }

    //查询订单状态
    @Override
    public Map<String, String> queryPayStatus(Long orderId) {
        //1.查询订单
        OrderInfo orderInfo =orderService.getOrder(orderId);
        //2.封装调用查询接口的参数
        Map<String,String> paramMap=new HashMap<>();
        paramMap.put("appid", ConstantPropertiesUtils.APPID);
        paramMap.put("mch_id", ConstantPropertiesUtils.PARTNER);
        paramMap.put("out_trade_no", orderInfo.getOutTradeNo());
        paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
        //3.通过httpclient请求
        HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
        try {
            client.setXmlParam(WXPayUtil.generateSignedXml(paramMap, ConstantPropertiesUtils.PARTNERKEY));
            client.setHttps(true);
            client.post();
            //4.获取第三方返回数据并转为map
            String xml = client.getContent();
            Map<String, String> resMap = WXPayUtil.xmlToMap(xml);
            //5.返回
            return resMap;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    //支付成功更新支付及订单信息
    @Override
    public void paySuccess(String outTradeNo, Integer payType, Map<String, String> restMap) {
        //1. 查询支付信息
        PaymentInfo paymentInfo = getPaymentInfo(outTradeNo, payType);
        if (paymentInfo==null){
            //1.1 为空
            throw new HospitalException(ResultCodeEnum.PARAM_ERROR);
        }
        if (paymentInfo.getPaymentStatus()!=PaymentStatusEnum.UNPAID.getStatus()){
            //1.2 已支付过了
            return;
        }
        //2. 设置更新支付状态
        paymentInfo.setPaymentStatus(PaymentStatusEnum.PAID.getStatus());//支付状态
        paymentInfo.setTradeNo(restMap.get("transaction_id"));//微信订单号
        paymentInfo.setCallbackTime(new Date());//回调时间
        paymentInfo.setCallbackContent(restMap.toString());//回调返回的信息
        this.baseMapper.updateById(paymentInfo);
        //3. 更新订单状态
        OrderInfo orderInfo = orderService.getOrder(paymentInfo.getOrderId());
        orderInfo.setOrderStatus(OrderStatusEnum.PAID.getStatus());//使用的是订单枚举
        orderService.updateById(orderInfo);
        //4. 调用医院接口支付状态
        SignInfoVo signInfoVo
                = hospFeignClient.getSignInfoVo(orderInfo.getHoscode());
        if(null == signInfoVo) {
            throw new HospitalException(ResultCodeEnum.PARAM_ERROR);
        }
        Map<String, Object> reqMap = new HashMap<>();
        reqMap.put("hoscode",orderInfo.getHoscode());
        reqMap.put("hosRecordId",orderInfo.getHosRecordId());
        reqMap.put("timestamp", HttpRequestHelper.getTimestamp());
        String sign = signInfoVo.getSignKey();
        reqMap.put("sign", sign);
        JSONObject result = HttpRequestHelper.sendRequest(reqMap, signInfoVo.getApiUrl()+"/order/updatePayStatus");
        if(result.getInteger("code") != 200) {
            throw new HospitalException(result.getString("message"), ResultCodeEnum.FAIL.getCode());
        }
    }

    //获取支付信息
    @Override
    public PaymentInfo getPayment(Long orderId, Integer payType) {
        QueryWrapper<PaymentInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("order_id",orderId);
        wrapper.eq("payment_type",payType);
        PaymentInfo paymentInfo = this.baseMapper.selectOne(wrapper);
        return paymentInfo;
    }

    //获取支付信息
    private PaymentInfo getPaymentInfo(String outTradeNo, Integer payType){
        QueryWrapper<PaymentInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("out_trade_no",outTradeNo);
        wrapper.eq("payment_type",payType);
        PaymentInfo paymentInfo = this.baseMapper.selectOne(wrapper);
        return paymentInfo;
    }


}
